package ltd.newbee.mall.config.aop;

import cn.hutool.core.util.StrUtil;
import ltd.newbee.mall.common.NewBeeMallException;
import ltd.newbee.mall.common.ServiceResultEnum;
import ltd.newbee.mall.config.CurrentAdminUser;
import ltd.newbee.mall.config.TokenAdminUser;
import ltd.newbee.mall.config.annotation.PreAuthorizeMethod;
import ltd.newbee.mall.entity.AdminPerm;
import ltd.newbee.mall.entity.AdminUser;
import ltd.newbee.mall.service.AdminPermService;
import ltd.newbee.mall.util.SpringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/***
 * 权限校验
 */
@Component
@Aspect
@Order(99)
public class AuthorityVerify {

    @Resource
    private AdminPermService adminPermService;

    @Resource
    private TokenAdminUser tokenAdminUser;

    @Resource
    private CurrentAdminUser currentAdminUser;

    /***
     * 配置切点
     */
    @Pointcut("@annotation(ltd.newbee.mall.config.annotation.PreAuthorizeMethod)")
    public void authPointCut() {

    }

    /**
     * 校验当前用户权限
     * @param joinPoint 切点
     * @exception Throwable
     */
    @Before("authPointCut()")
    public void execAction(JoinPoint joinPoint) throws Throwable {
        PreAuthorizeMethod authorize = this.authorizeMethod(joinPoint);
        if (authorize != null) {
            AdminUser user = currentAdminUser.currentLoginUser();
            if (!user.getAdminUserId().equals(1L)) {
                String permission = authorize.value();
                HttpServletRequest request = SpringUtils.currentRequest();
                String token = request.getHeader(tokenAdminUser.getHeader());
                List<AdminPerm> perms = adminPermService.selectAdminUserPermByToken(token);
                Set<String> sets = perms.stream().map(AdminPerm::getPerm).collect(Collectors.toSet());
                if (!this.hasPermissions(sets, permission)) {
                    NewBeeMallException.fail(ServiceResultEnum.NOT_PERM.getResult());
                }
            }
        }

    }

    /**
     * 是否存在注解，如果存在就获取
     */
    private PreAuthorizeMethod authorizeMethod(JoinPoint joinPoint) {
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();
        if (method != null) {
            return method.getAnnotation(PreAuthorizeMethod.class);
        }
        return null;
    }

    /**
     * 判断是否包含权限
     *
     * @param permissions 权限列表
     * @param permission  权限字符串
     * @return 用户是否具备某权限
     */
    private boolean hasPermissions(Set<String> permissions, String permission) {
        return permissions.contains(StrUtil.trim(permission));
    }
}
